﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Media.Animation;

namespace SuperKinhLuan.Games.Quadronica
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class MainPage : Page
    {
        private const int AnimationDuratoinInMiliseconds = 300;

        private static Color[] AllColors = new Color[]
        {
            Colors.LightGreen,
            Colors.Green,
            Colors.Magenta,
            Colors.Yellow,
            Colors.Red,
            Colors.Blue
        };

        private Square selectedSquare;
        private Storyboard effectStoryboard, errorStoryboard;
        private bool isAnimationPlaying;
        private int X1, Y1, X2, Y2;

        public MainPage()
        {
            InitializeComponent();

            AddHandler(Square.SelectedEvent, new RoutedEventHandler(HandleSelectedEvent));
            AddHandler(Square.UnselectedEvent, new RoutedEventHandler(HandleUnselectedEvent));

            this.effectStoryboard = new Storyboard();
            this.effectStoryboard.Duration = new Duration(TimeSpan.FromMilliseconds(AnimationDuratoinInMiliseconds));
            this.effectStoryboard.Completed += new EventHandler(AnimationCompleted);

            this.errorStoryboard = this.FindResource("ErrorAnimation") as Storyboard;
        }

        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnPreviewMouseLeftButtonDown(e);

            if (isAnimationPlaying)
            {
                Point p = e.GetPosition(MainBoard);
                if (p.X >= 0 && p.X <= MainBoard.ActualWidth && p.Y >= 0 && p.Y <= MainBoard.ActualHeight)
                {
                    e.Handled = true;
                }
            }
        }

        private void AnimationCompleted(object sender, EventArgs e)
        {
            this.isAnimationPlaying = false;
            SetColorInRectangle(this.X1, this.Y1, this.X2, this.Y2);
        }

        private void HandleSelectedEvent(object sender, RoutedEventArgs args)
        {
            Square source = (Square)args.Source;
            if (selectedSquare == null)
            {
                selectedSquare = source;
            }
            else
            {
                if (IsValid(selectedSquare, source))
                {
                    ChangeColor(selectedSquare, source);
                }
                else
                {
                    this.errorStoryboard.Begin(BoardBorder);
                }

                selectedSquare.IsSelected = source.IsSelected = false;
                selectedSquare = null;
            }
        }

        private void HandleUnselectedEvent(object sender, RoutedEventArgs args)
        {
            selectedSquare = null;
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 81; i++)
            {
                string transformName = "transform" + i;

                ScaleTransform transform = new ScaleTransform(1, 1, 0.5, 0.5);
                this.RegisterName(transformName, transform);

                DoubleAnimation scaleXAnimation = new DoubleAnimation(
                    0, 
                    new Duration(TimeSpan.FromMilliseconds(AnimationDuratoinInMiliseconds)), 
                    FillBehavior.Stop);
                Storyboard.SetTargetName(scaleXAnimation, transformName);
                Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("ScaleX"));

                DoubleAnimation scaleYAnimation = new DoubleAnimation(
                    0, 
                    new Duration(TimeSpan.FromMilliseconds(AnimationDuratoinInMiliseconds)), 
                    FillBehavior.Stop);
                Storyboard.SetTargetName(scaleYAnimation, transformName);
                Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("ScaleY"));

                ParallelTimeline animation = new ParallelTimeline();
                animation.Children.Add(scaleXAnimation);
                animation.Children.Add(scaleYAnimation);

                Square s = new Square 
                { 
                    Tag = animation, 
                    RenderTransform = transform,
                    RenderTransformOrigin = new Point(0.5, 0.5),
                    Index = i
                };

                MainBoard.Children.Add(s);
            }

            SetColorInRectangle(0, 0, 8, 8);
        }

        private bool IsValid(Square first, Square second)
        {
            Debug.Assert(first != null);
            Debug.Assert(second != null);
            if (first.Color != second.Color) return false;

            int x1 = first.Index / 9;
            int y1 = first.Index % 9;

            int x2 = second.Index / 9;
            int y2 = second.Index % 9;

            if (x1 == x2 || y1 == y2) return false;

            Square third = (Square)MainBoard.Children[x1 * 9 + y2];
            if (third.Color != first.Color) return false;

            Square fourth = (Square)MainBoard.Children[x2 * 9 + y1];
            if (fourth.Color != first.Color) return false;

            return true;
        }

        private void ChangeColor(Square first, Square second)
        {
            Debug.Assert(first != null);
            Debug.Assert(second != null);

            int x1 = Math.Min(first.Index / 9, second.Index / 9);
            int y1 = Math.Min(first.Index % 9, second.Index % 9);

            int x2 = Math.Max(first.Index / 9, second.Index / 9);
            int y2 = Math.Max(first.Index % 9, second.Index % 9);

            effectStoryboard.Children.Clear();
            for (int i = x1; i <= x2; i++)
            {
                for (int j = y1; j <= y2; j++)
                {
                    Square s = (Square)MainBoard.Children[i * 9 + j];
                    effectStoryboard.Children.Add((Timeline)s.Tag);
                }
            }

            effectStoryboard.Stop();
            this.isAnimationPlaying = true;
            this.X1 = x1;
            this.Y1 = y1;
            this.X2 = x2;
            this.Y2 = y2;
            effectStoryboard.Begin(this);
        }

        private void SetColorInRectangle(int x1, int y1, int x2, int y2)
        {
            Random r = new Random();
            for (int i = x1; i <= x2; i++)
            {
                for (int j = y1; j <= y2; j++)
                {
                    Square s = (Square)MainBoard.Children[i * 9 + j];
                    s.Color = AllColors[r.Next(6)];
                }
            }
        }
    }
}